----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    21:32:54 12/02/2014 
-- Design Name: 
-- Module Name:    IF_ram2 - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
--instruction fetch只有读取内存的功能

entity IF_ram2 is
	port(
		CLK, RST: IN STD_LOGIC;
--		使能端，判断该pc能否使用
		EN: IN STD_LOGIC;
--		程序计数器program counter
		pc: IN STD_LOGIC_VECTOR(15 DOWNTO 0);
--		从ram2中相应地址读出指令数据
		Ram2Addr: OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
		Ram2Data: INOUT STD_LOGIC_VECTOR(15 DOWNTO 0);
--		根据pc地址输出相应指令
		instruction: OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
		Ram2OE, Ram2WE, Ram2EN: OUT STD_LOGIC
	);
end IF_ram2;

architecture Behavioral of IF_ram2 is
type task is (init_addr_2, read_ram2, state_nop);
signal state : task := init_addr_2;
begin
--这个时钟可以由外部时钟控制，即不与流水线时钟周期一致？
--因为从ram2中取出指令至少需要两个CLK周期
process(CLK, RST, EN)
begin
	if RST = '0' then
		state <= init_addr_2;
	elsif CLK'event and CLK = '1' then
		case state is 
			when init_addr_2 =>
				Ram2EN <= '0';
				Ram2OE <= '1';
				Ram2WE <= '1';
				if EN = '0' then
					state <= read_ram2;
					Ram2Addr(17 downto 16) <= "00";
					Ram2Addr(15 downto 0) <= pc;
					Ram2Data <= (others=>'Z');
					Ram2OE <= '0';
				else 
					state <= init_addr_2;
--					若pc不可用，则输出nop指令
					instruction <= "0000100000000000";
				end if;
			when read_ram2 =>
--				假定使能为0表示可以使用pc地址
				instruction <= Ram2Data;
				Ram2OE <= '1';
				state <= init_addr_2;
			when others =>
		end case;
	end if;
end process;
end Behavioral;

